import {
	get
} from 'lodash'
import router from '@/router'
import setting from '@/setting.js'
import store from '@/store/index'

// 判定是否需要缓存
const isKeepAlive = data => get(data, 'meta.cache', false)

export default {
	namespaced: true,
	state: {
		info: {},
		// 可以在多页 tab 模式下显示的页面
		pool: [],
		// 当前显示的多页面列表
		opened: setting.page.opened,
		// 已经加载多标签页数据 https://github.com/d2-projects/d2-admin/issues/201
		openedLoaded: false,
		// 当前页面
		current: '',
		// 需要缓存的页面 name
		keepAlive: []
	},
	actions: {
		/**
		 * @description 设置page
		 * @param {Object} state vuex state
		 * @param {String} size 页面
		 */
		setActivePage({
			state,
			dispatch
		}, activePage) {
			console.warn('=========设置page');
			return new Promise(async resolve => {
				// 持久化
				await dispatch('d2admin/db/set', {
					dbName: 'sys',
					path: 'page.activePage',
					value: activePage||'',
					user: true
				}, {
					root: true
				})
				// end
				resolve()
			})
		},
		/**
		 * @description 确认已经加载多标签页数据 https://github.com/d2-projects/d2-admin/issues/201
		 */
		isLoaded({
			state
		}) {
			if (state.value) return Promise.resolve()
			return new Promise(resolve => {
				const timer = setInterval(() => {
					if (state.openedLoaded) {
						resolve(clearInterval(timer))
					}
				}, 10)
			})
		},
		/**
		 * @class opened
		 * @description 从持久化数据载入标签页列表
		 * @param {Object} state vuex state
		 */
		openedLoad({
			state,
			commit,
			dispatch
		}) {
			console.warn('====载入标签页列表====');
			return new Promise(async resolve => {
				// store 赋值
				const value = await dispatch('d2admin/db/get', {
					dbName: 'sys',
					path: 'page.opened',
					defaultValue: setting.page.opened,
					user: true
				}, {
					root: true
				})
				// 在处理函数中进行数据优化 过滤掉现在已经失效的页签或者已经改变了信息的页签
				// 以 fullPath 字段为准
				// 如果页面过多的话可能需要优化算法
				// valid 有效列表 1, 1, 0, 1 => 有效, 有效, 失效, 有效
				const valid = []
				// 处理数据
				state.opened = value.map((opened,idx) => {
					// 初始-有效
					valid[idx] = 1;
					// 忽略首页
					if (opened.fullPath === '/index') {
						console.warn('====忽略首页===');
						return opened
					}
					// 尝试在所有的支持多标签页的页面里找到 name 匹配的页面
					// const find = state.pool.find(item => item.name === opened.name);
					// if(!find){
					// 	console.warn('===========没有找到 name 匹配的页面');
					// 	console.log();
					// }
					// // 记录有效或无效信息
					// valid[idx] = find ? 1 : 0;
					
					
					//忽略没有权限的页面
					try{
						let newopened = opened.path.replace('-',':')+':index';
						if(Array.isArray(store.state.d2admin.user.info.permissions)){
							let isAuthority = store.state.d2admin.user.info.permissions.includes(newopened);
							if(!isAuthority){
								valid[idx] = 0;
								console.warn('没有权限的=='+opened.path);
							}
						}
					}catch(e){
					}
					
					// 返回合并后的数据 新的覆盖旧的
					// 新的数据中一般不会携带 params 和 query, 所以旧的参数会留存
					return Object.assign({}, opened)
				}).filter((opened, index) => valid[index] === 1);
				console.warn('==================');
				console.log(state.opened);
				console.log(valid);
				if(valid.length&&valid.includes(0)){
					console.warn('======有无效的信息==========');
					if(state.opened.length){
						let fullPath = state.opened[state.opened.length-1].fullPath;
						if(fullPath){
							console.warn(`=======重新设置当前页：${fullPath}===========`);
							await dispatch('setActivePage', fullPath);
						}
					}else{
						console.warn(`=======重新设置当前页：空===========`);
						await dispatch('closeAll');
					}
				}
				// 标记已经加载多标签页数据 https://github.com/d2-projects/d2-admin/issues/201
				state.openedLoaded = true;
				// console.warn('====打开的页面===');
				// console.log(store.state.d2admin.permission.permissions);
				// console.log(state.opened);
				// 根据 opened 数据生成缓存设置
				commit('keepAliveRefresh')
				// end
				resolve()
			})
		},
		/**
		 * 将 opened 属性赋值并持久化 在这之前请先确保已经更新了 state.opened
		 * @param {Object} state vuex state
		 */
		opend2db({
			state,
			dispatch
		}, {
			type
		}) {
			console.warn('重新设置打开的选项tab' + type);
			console.log(state);
			if (state.opened.length == 1) {
				if (Array.isArray(state.pool)) {
					if (state.pool.length) {
						let poolFirst = state.pool[0],
							p_path = poolFirst.path,
							lastDashIndex = p_path.lastIndexOf('-');
						if (lastDashIndex != -1) {
							let p_fullPath = p_path.substring(lastDashIndex + 1);
							if (p_fullPath) {
								console.log('/' + p_fullPath);
							}
						}
					}
				}
			} else {

			}
			return new Promise(async resolve => {
				// 设置数据
				dispatch('d2admin/db/set', {
					dbName: 'sys',
					path: 'page.opened',
					value: state.opened,
					user: true
				}, {
					root: true
				})
				// end
				resolve()
			})
		},
		/**
		 * @class opened
		 * @description 更新页面列表上的某一项
		 * @param {Object} state vuex state
		 * @param {Object} param { index, params, query, fullPath } 路由信息
		 */
		openedUpdate({
			state,
			commit,
			dispatch
		}, {
			index,
			params,
			query,
			fullPath
		}) {
			console.warn('更新页面列表上的某一项');
			// 持久化当前激活的页面
			return new Promise(async resolve => {
				// 更新页面列表某一项
				await dispatch('setActivePage', fullPath || page.fullPath);
				const page = state.opened[index]
				page.params = params || page.params
				page.query = query || page.query
				page.fullPath = fullPath || page.fullPath
				state.opened.splice(index, 1, page)
				// 持久化
				await dispatch('opend2db', {
					type: 'openedUpdate'
				})
				// end
				resolve()
			})
		},
		/**
		 * @class opened
		 * @description 新增一个 tag (打开一个页面)
		 * @param {Object} state vuex state
		 * @param {Object} param new tag info
		 */
		add({
			state,
			commit,
			dispatch
		}, {
			tag,
			params,
			query,
			fullPath
		}) {
			console.log('新增一个 tag (打开一个页面)');
			console.log(tag);
			console.log(state.opened);
			// console.log('1111111111111111111111111111111111');
			return new Promise(async resolve => {
				// 设置新的 tag 在新打开一个以前没打开过的页面时使用
				const newTag = tag
				newTag.params = params || newTag.params
				newTag.query = query || newTag.query
				newTag.fullPath = fullPath || newTag.fullPath
				await dispatch('setActivePage', newTag.fullPath);
				// 添加进当前显示的页面数组
				state.opened.push(newTag)
				// 如果这个页面需要缓存 将其添加到缓存设置
				if (isKeepAlive(newTag)) {
					commit('keepAlivePush', tag.name)
				}
				// 持久化
				await dispatch('opend2db', {
					type: 'add'
				})
				// end
				resolve()
			})
		},
		/**
		 * @class current
		 * @description 打开一个新的页面
		 * @param {Object} state vuex state
		 * @param {Object} param 从路由钩子的 to 对象上获取 { name, params, query, fullPath } 路由信息
		 */
		open({
			state,
			commit,
			dispatch
		}, {
			name,
			params,
			query,
			fullPath
		}) {
			console.warn('=====打开一个新的页面=====');
			return new Promise(async resolve => {
				// 已经打开的页面
				const opened = state.opened
				// 判断此页面是否已经打开 并且记录位置
				let pageOpendIndex = 0
				const pageOpend = opened.find((page, index) => {
					const same = page.fullPath === fullPath
					pageOpendIndex = same ? index : pageOpendIndex
					return same
				})
				if (pageOpend) {
					console.warn('页面以前打开过====');
					// 页面以前打开过
					await dispatch('openedUpdate', {
						index: pageOpendIndex,
						params,
						query,
						fullPath
					})
				} else {
					console.warn('页面以前没有打开过====');
					// 页面以前没有打开过
					const page = state.pool.find(t => t.name === name)
					// 如果这里没有找到 page 代表这个路由虽然在框架内 但是不参与标签页显示
					if (page) {
						await dispatch('add', {
							tag: Object.assign({}, page),
							params,
							query,
							fullPath
						})
					}
				}
				commit('currentSet', fullPath)
				// end
				resolve()
			})
		},
		/**
		 * @class opened
		 * @description 关闭一个 tag (关闭一个页面)
		 * @param {Object} state vuex state
		 * @param {Object} param { tagName: 要关闭的标签名字 }
		 */
		close({
			state,
			commit,
			dispatch
		}, {
			tagName
		}) {
			return new Promise(async resolve => {
				// 下个新的页面
				let newPage = state.opened[0]
				const isCurrent = state.current === tagName
				// 如果关闭的页面就是当前显示的页面
				if (isCurrent) {
					// 去找一个新的页面
					const len = state.opened.length
					for (let i = 1; i < len; i++) {
						if (state.opened[i].fullPath === tagName) {
							if (i < len - 1) {
								newPage = state.opened[i + 1]
							} else {
								newPage = state.opened[i - 1]
							}
							break
						}
					}
				}
				// 找到这个页面在已经打开的数据里是第几个
				const index = state.opened.findIndex(page => page.fullPath === tagName)
				if (index >= 0) {
					// 如果这个页面是缓存的页面 将其在缓存设置中删除
					commit('keepAliveRemove', state.opened[index].name)
					// 更新数据 删除关闭的页面
					state.opened.splice(index, 1)
				}
				// 持久化
				await dispatch('opend2db', {
					type: 'close'
				})
				// 标签页没有了跳到首页
				if (state.opened.length == 0) {
					dispatch('closeAll');
					return
				}
				// 关闭当前标签页跳转一个标签页
				if (isCurrent) {
					const {
						name = '', params = {}, query = {}
					} = newPage
					const routerObj = {
						name,
						params,
						query
					}
					router.push(routerObj)
				}
				// end
				resolve()
			})
		},
		/**
		 * @class opened
		 * @description 关闭当前标签左边的标签
		 * @param {Object} state vuex state
		 * @param {Object} param { pageSelect: 当前选中的tagName }
		 */
		closeLeft({
			state,
			commit,
			dispatch
		}, {
			pageSelect
		} = {}) {
			return new Promise(async resolve => {
				const pageAim = pageSelect || state.current
				let currentIndex = 0
				state.opened.forEach((page, index) => {
					if (page.fullPath === pageAim) {
						currentIndex = index
					}
				})
				if (currentIndex > 0) {
					// 删除打开的页面 并在缓存设置中删除
					state.opened.splice(0, currentIndex).forEach(({
						name
					}) => commit('keepAliveRemove', name))
				}
				state.current = pageAim
				if (router.app.$route.fullPath !== pageAim) {
					router.push(pageAim)
				}
				// 持久化
				await dispatch('opend2db', {
					type: 'closeLeft'
				})
				// end
				resolve()
			})
		},
		/**
		 * @class opened
		 * @description 关闭当前标签右边的标签
		 * @param {Object} state vuex state
		 * @param {Object} param { pageSelect: 当前选中的tagName }
		 */
		closeRight({
			state,
			commit,
			dispatch
		}, {
			pageSelect
		} = {}) {
			return new Promise(async resolve => {
				const pageAim = pageSelect || state.current
				let currentIndex = 0
				state.opened.forEach((page, index) => {
					if (page.fullPath === pageAim) {
						currentIndex = index
					}
				})
				// 删除打开的页面 并在缓存设置中删除
				state.opened.splice(currentIndex + 1).forEach(({
					name
				}) => commit('keepAliveRemove', name))
				// 设置当前的页面
				state.current = pageAim
				if (router.app.$route.fullPath !== pageAim) {
					router.push(pageAim)
				}
				// 持久化
				await dispatch('opend2db', {
					type: 'closeRight'
				})
				// end
				resolve()
			})
		},
		/**
		 * @class opened
		 * @description 关闭当前激活之外的 tag
		 * @param {Object} state vuex state
		 * @param {Object} param { pageSelect: 当前选中的tagName }
		 */
		closeOther({
			state,
			commit,
			dispatch
		}, {
			pageSelect
		} = {}) {
			return new Promise(async resolve => {
				const pageAim = pageSelect || state.current
				let currentIndex = 0
				state.opened.forEach((page, index) => {
					if (page.fullPath === pageAim) {
						currentIndex = index
					}
				})
				// 删除打开的页面数据 并更新缓存设置
				if (currentIndex === 0) {
					state.opened.splice(1).forEach(({
						name
					}) => commit('keepAliveRemove', name))
				} else {
					state.opened.splice(currentIndex + 1).forEach(({
						name
					}) => commit('keepAliveRemove', name))
					state.opened.splice(0, currentIndex).forEach(({
						name
					}) => commit('keepAliveRemove', name))
				}
				// 设置新的页面
				state.current = pageAim
				if (router.app.$route.fullPath !== pageAim) {
					router.push(pageAim)
				}
				console.log(pageAim);
				// 持久化
				await dispatch('opend2db', {
					type: 'closeOther'
				})
				// end
				resolve()
			})
		},
		/**
		 * @class opened
		 * @description 关闭所有 tag
		 * @param {Object} state vuex state
		 */
		closeAll({
			state,
			commit,
			dispatch
		}) {
			console.warn('===关闭所有===');
			return new Promise(async resolve => {
				dispatch('setActivePage', '');
				commit('d2admin/menu/asideSet', {
					menu: [],
					pid: -1
				}, {
					root: true
				});
				// 删除打开的页面 并在缓存设置中删除
				state.opened.splice(1).forEach(({
					name
				}) => commit('keepAliveRemove', name))
				// 持久化
				state.opened = [];
				await dispatch('opend2db', {
					type: 'closeAll'
				})
				// 关闭所有的标签页后需要判断一次现在是不是在首页
				if (router.app.$route.name !== 'index') {
					router.push({
						name: 'index'
					})
				}
				// end
				resolve()
			})
		}
	},
	mutations: {
		/**
		 * @class keepAlive
		 * @description 从已经打开的页面记录中更新需要缓存的页面记录
		 * @param {Object} state vuex state
		 */
		keepAliveRefresh(state) {
			state.keepAlive = state.opened.filter(item => isKeepAlive(item)).map(e => e.name)
		},
		/**
		 * @description 删除一个页面的缓存设置
		 * @param {Object} state vuex state
		 * @param {String} name name
		 */
		keepAliveRemove(state, name) {
			const list = [...state.keepAlive]
			const index = list.findIndex(item => item === name)

			if (index !== -1) {
				list.splice(index, 1)
				state.keepAlive = list
			}
		},
		/**
		 * @description 增加一个页面的缓存设置
		 * @param {Object} state vuex state
		 * @param {String} name name
		 */
		keepAlivePush(state, name) {
			const keep = [...state.keepAlive]
			keep.push(name)
			state.keepAlive = keep
		},
		/**
		 * @description 清空页面缓存设置
		 * @param {Object} state vuex state
		 */
		keepAliveClean(state) {
			state.keepAlive = []
		},
		/**
		 * @class current
		 * @description 设置当前激活的页面 fullPath
		 * @param {Object} state vuex state
		 * @param {String} fullPath new fullPath
		 */
		currentSet(state, fullPath) {
			console.warn(`=======设置当前激活的页面=>${fullPath}=========`);
			console.log(setting.page);
			if (setting.page.activePage) {
				state.current = setting.page.activePage;
				return
			}
			state.current = fullPath
		},
		/**
		 * @class pool
		 * @description 保存 pool (候选池)
		 * @param {Object} state vuex state
		 * @param {Array} routes routes
		 */
		init(state, routes) {
			const pool = []
			const push = function(routes) {
				routes.forEach(route => {
					if (route.children) {
						push(route.children)
					} else {
						if (!route.hidden) {
							const {
								meta,
								name,
								path
							} = route
							pool.push({
								meta,
								name,
								path
							})
						}
					}
				})
			}
			push(routes)
			state.pool = pool
		}
	}
}